package basics.collections;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * Java 集合常见操作示例
 * 
 * 本类提供了各种集合操作的实际示例，可以运行查看结果
 */
public class CollectionOperationsDemo {
    
    public static void main(String[] args) {
        System.out.println("===== Java 集合操作示例 =====");
        
        // List操作示例
        listOperations();
        
        // Set操作示例
        setOperations();
        
        // Map操作示例
        mapOperations();
        
        // Queue操作示例
        queueOperations();
        
        // 集合工具类示例
        collectionsUtilDemo();
        
        // 集合与数组互相转换
        collectionArrayConversion();
        
        // Java 8+ 新特性
        java8Features();
    }
    
    /**
     * List接口实现类的操作示例
     */
    private static void listOperations() {
        System.out.println("\n----- List操作示例 -----");
        
        // ArrayList示例
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("C++");
        arrayList.add("JavaScript");
        
        System.out.println("ArrayList: " + arrayList);
        
        // 访问元素
        System.out.println("第一个元素: " + arrayList.get(0));
        System.out.println("最后一个元素: " + arrayList.get(arrayList.size() - 1));
        
        // 修改元素
        arrayList.set(1, "Python 3");
        System.out.println("修改后的ArrayList: " + arrayList);
        
        // 插入元素
        arrayList.add(2, "C#");
        System.out.println("插入元素后的ArrayList: " + arrayList);
        
        // 删除元素
        arrayList.remove("C++");
        System.out.println("删除元素后的ArrayList: " + arrayList);
        
        // 查找元素
        System.out.println("Java的索引: " + arrayList.indexOf("Java"));
        System.out.println("是否包含Kotlin: " + arrayList.contains("Kotlin"));
        
        // LinkedList示例
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("红色");
        linkedList.add("绿色");
        linkedList.add("蓝色");
        
        System.out.println("\nLinkedList: " + linkedList);
        
        // LinkedList特有的操作
        linkedList.addFirst("黑色");
        linkedList.addLast("白色");
        System.out.println("添加首尾元素后: " + linkedList);
        
        System.out.println("第一个元素: " + linkedList.getFirst());
        System.out.println("最后一个元素: " + linkedList.getLast());
        
        linkedList.removeFirst();
        linkedList.removeLast();
        System.out.println("删除首尾元素后: " + linkedList);
        
        // 线程安全的List
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        synchronizedList.add("线程安全的元素");
        
        List<String> copyOnWriteList = new CopyOnWriteArrayList<>();
        copyOnWriteList.add("适合读多写少的场景");
        
        System.out.println("\n线程安全的List示例:");
        System.out.println("synchronizedList: " + synchronizedList);
        System.out.println("copyOnWriteList: " + copyOnWriteList);
    }
    
    /**
     * Set接口实现类的操作示例
     */
    private static void setOperations() {
        System.out.println("\n----- Set操作示例 -----");
        
        // HashSet示例
        Set<String> hashSet = new HashSet<>();
        hashSet.add("Java");
        hashSet.add("Python");
        hashSet.add("C++");
        hashSet.add("Java"); // 重复元素不会被添加
        
        System.out.println("HashSet: " + hashSet);
        System.out.println("HashSet大小: " + hashSet.size());
        System.out.println("是否包含Java: " + hashSet.contains("Java"));
        
        // 删除元素
        hashSet.remove("C++");
        System.out.println("删除元素后的HashSet: " + hashSet);
        
        // LinkedHashSet示例
        Set<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("Java");
        linkedHashSet.add("Python");
        linkedHashSet.add("C++");
        linkedHashSet.add("JavaScript");
        
        System.out.println("\nLinkedHashSet（保持插入顺序）: " + linkedHashSet);
        
        // TreeSet示例
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("Banana");
        treeSet.add("Apple");
        treeSet.add("Orange");
        treeSet.add("Grape");
        
        System.out.println("\nTreeSet（自然排序）: " + treeSet);
        
        // TreeSet的导航方法
        System.out.println("第一个元素: " + treeSet.first());
        System.out.println("最后一个元素: " + treeSet.last());
        System.out.println("小于Orange的最大元素: " + treeSet.lower("Orange"));
        System.out.println("大于Orange的最小元素: " + treeSet.higher("Orange"));
        
        // 子集
        System.out.println("Apple到Orange的子集: " + treeSet.subSet("Apple", "Orange"));
        System.out.println("小于等于Grape的元素: " + treeSet.headSet("Grape", true));
        System.out.println("大于等于Banana的元素: " + treeSet.tailSet("Banana", true));
    }
    
    /**
     * Map接口实现类的操作示例
     */
    private static void mapOperations() {
        System.out.println("\n----- Map操作示例 -----");
        
        // HashMap示例
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("Java", 1995);
        hashMap.put("Python", 1991);
        hashMap.put("C++", 1983);
        hashMap.put("JavaScript", 1995);
        
        System.out.println("HashMap: " + hashMap);
        
        // 访问元素
        System.out.println("Java发布年份: " + hashMap.get("Java"));
        System.out.println("Ruby发布年份: " + hashMap.get("Ruby")); // 不存在的键返回null
        System.out.println("Ruby发布年份（提供默认值）: " + hashMap.getOrDefault("Ruby", 0));
        
        // 检查键和值
        System.out.println("是否包含键Python: " + hashMap.containsKey("Python"));
        System.out.println("是否包含值1995: " + hashMap.containsValue(1995));
        
        // 修改元素
        hashMap.put("Python", 1989); // 更新已存在的键
        System.out.println("更新后的HashMap: " + hashMap);
        
        // 删除元素
        hashMap.remove("JavaScript");
        System.out.println("删除元素后的HashMap: " + hashMap);
        
        // 遍历Map
        System.out.println("\n遍历HashMap:");
        
        // 方式1：使用entrySet
        for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // 方式2：使用keySet和get
        System.out.println("\n使用keySet遍历:");
        for (String key : hashMap.keySet()) {
            System.out.println(key + ": " + hashMap.get(key));
        }
        
        // 方式3：使用forEach（Java 8+）
        System.out.println("\n使用forEach遍历:");
        hashMap.forEach((key, value) -> System.out.println(key + ": " + value));
        
        // LinkedHashMap示例
        Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("Java", 1995);
        linkedHashMap.put("Python", 1991);
        linkedHashMap.put("C++", 1983);
        linkedHashMap.put("JavaScript", 1995);
        
        System.out.println("\nLinkedHashMap（保持插入顺序）: " + linkedHashMap);
        
        // TreeMap示例
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("Java", 1995);
        treeMap.put("Python", 1991);
        treeMap.put("C++", 1983);
        treeMap.put("JavaScript", 1995);
        
        System.out.println("\nTreeMap（按键排序）: " + treeMap);
        
        // TreeMap的导航方法
        System.out.println("第一个键: " + treeMap.firstKey());
        System.out.println("最后一个键: " + treeMap.lastKey());
        System.out.println("小于Python的最大键: " + treeMap.lowerKey("Python"));
        System.out.println("大于Python的最小键: " + treeMap.higherKey("Python"));
        
        // 子Map
        System.out.println("C++到Python的子Map: " + treeMap.subMap("C++", "Python"));
        
        // 线程安全的Map
        Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
        concurrentMap.put("线程安全的键", 1);
        
        System.out.println("\n线程安全的Map示例:");
        System.out.println("concurrentMap: " + concurrentMap);
    }
    
    /**
     * Queue接口实现类的操作示例
     */
    private static void queueOperations() {
        System.out.println("\n----- Queue操作示例 -----");
        
        // LinkedList作为Queue使用
        Queue<String> queue = new LinkedList<>();
        queue.offer("第一个");
        queue.offer("第二个");
        queue.offer("第三个");
        
        System.out.println("Queue: " + queue);
        
        // 查看队首元素但不移除
        System.out.println("队首元素: " + queue.peek());
        
        // 移除并返回队首元素
        System.out.println("移除的元素: " + queue.poll());
        System.out.println("移除后的Queue: " + queue);
        
        // PriorityQueue示例
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(5);
        priorityQueue.offer(1);
        priorityQueue.offer(3);
        priorityQueue.offer(2);
        priorityQueue.offer(4);
        
        System.out.println("\nPriorityQueue: " + priorityQueue);
        
        // 移除元素（按优先级顺序）
        System.out.println("移除的元素顺序:");
        while (!priorityQueue.isEmpty()) {
            System.out.print(priorityQueue.poll() + " ");
        }
        System.out.println();
        
        // Deque示例（双端队列）
        Deque<String> deque = new ArrayDeque<>();
        deque.addFirst("第一个");
        deque.addLast("最后一个");
        deque.addFirst("新的第一个");
        deque.addLast("新的最后一个");
        
        System.out.println("\nDeque: " + deque);
        
        // 作为栈使用
        System.out.println("弹出元素（栈）: " + deque.pop()); // 移除并返回第一个元素
        System.out.println("弹出后的Deque: " + deque);
        
        // 作为队列使用
        System.out.println("移除队首元素（队列）: " + deque.removeFirst());
        System.out.println("移除队尾元素（队列）: " + deque.removeLast());
        System.out.println("最终的Deque: " + deque);
    }
    
    /**
     * Collections工具类示例
     */
    private static void collectionsUtilDemo() {
        System.out.println("\n----- Collections工具类示例 -----");
        
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(9);
        numbers.add(3);
        
        System.out.println("原始List: " + numbers);
        
        // 排序
        Collections.sort(numbers);
        System.out.println("排序后: " + numbers);
        
        // 二分查找（要求已排序）
        int index = Collections.binarySearch(numbers, 8);
        System.out.println("8的索引: " + index);
        
        // 反转
        Collections.reverse(numbers);
        System.out.println("反转后: " + numbers);
        
        // 打乱
        Collections.shuffle(numbers);
        System.out.println("打乱后: " + numbers);
        
        // 最大值和最小值
        int max = Collections.max(numbers);
        int min = Collections.min(numbers);
        System.out.println("最大值: " + max);
        System.out.println("最小值: " + min);
        
        // 填充
        List<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Orange");
        System.out.println("\n原始水果List: " + fruits);
        
        Collections.fill(fruits, "Grape");
        System.out.println("填充后: " + fruits);
        
        // 不可修改的集合
        List<String> immutableList = Collections.unmodifiableList(
            Arrays.asList("不可修改的元素1", "不可修改的元素2")
        );
        System.out.println("\n不可修改的List: " + immutableList);
        
        try {
            immutableList.add("新元素"); // 会抛出UnsupportedOperationException
        } catch (UnsupportedOperationException e) {
            System.out.println("尝试修改不可修改的List时抛出异常");
        }
        
        // 频率
        List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "apple", "grape");
        int frequency = Collections.frequency(words, "apple");
        System.out.println("\n'apple'在List中出现的次数: " + frequency);
        
        // 是否没有共同元素
        List<String> list1 = Arrays.asList("a", "b", "c");
        List<String> list2 = Arrays.asList("d", "e", "f");
        boolean disjoint = Collections.disjoint(list1, list2);
        System.out.println("list1和list2是否没有共同元素: " + disjoint);
    }
    
    /**
     * 集合与数组互相转换示例
     */
    private static void collectionArrayConversion() {
        System.out.println("\n----- 集合与数组互相转换 -----");
        
        // 数组转List
        String[] array = {"Java", "Python", "C++", "JavaScript"};
        
        // 使用Arrays.asList
        List<String> list1 = Arrays.asList(array);
        System.out.println("Arrays.asList结果: " + list1);
        
        // 创建可修改的ArrayList
        List<String> list2 = new ArrayList<>(Arrays.asList(array));
        list2.add("Ruby");
        System.out.println("可修改的ArrayList: " + list2);
        
        // 基本类型数组转List
        int[] intArray = {1, 2, 3, 4, 5};
        
        // 错误方式：直接使用Arrays.asList
        List<?> wrongList = Arrays.asList(intArray); // 会将整个数组作为一个元素
        System.out.println("错误的转换方式: " + wrongList);
        
        // 正确方式：使用包装类或手动转换
        List<Integer> correctList = new ArrayList<>();
        for (int value : intArray) {
            correctList.add(value);
        }
        System.out.println("正确的转换方式: " + correctList);
        
        // 使用Stream API（Java 8+）
        List<Integer> streamList = Arrays.stream(intArray).boxed().collect(Collectors.toList());
        System.out.println("使用Stream API转换: " + streamList);
        
        // List转数组
        List<String> languageList = new ArrayList<>();
        languageList.add("Java");
        languageList.add("Python");
        languageList.add("C++");
        
        // 转换为Object数组
        Object[] objectArray = languageList.toArray();
        System.out.println("\ntoArray()结果: " + Arrays.toString(objectArray));
        
        // 转换为指定类型的数组
        String[] stringArray = languageList.toArray(new String[0]);
        System.out.println("toArray(new String[0])结果: " + Arrays.toString(stringArray));
        
        // 使用Stream API（Java 8+）
        String[] streamArray = languageList.stream().toArray(String[]::new);
        System.out.println("使用Stream API转换: " + Arrays.toString(streamArray));
    }
    
    /**
     * Java 8+新特性示例
     */
    private static void java8Features() {
        System.out.println("\n----- Java 8+新特性 -----");
        
        List<String> languages = Arrays.asList(
            "Java", "Python", "JavaScript", "C++", "Ruby", "Go", "Swift", "Kotlin"
        );
        
        System.out.println("原始List: " + languages);
        
        // Stream API - 过滤
        List<String> filtered = languages.stream()
            .filter(lang -> lang.length() > 4)
            .collect(Collectors.toList());
        
        System.out.println("长度大于4的语言: " + filtered);
        
        // Stream API - 映射
        List<Integer> lengths = languages.stream()
            .map(String::length)
            .collect(Collectors.toList());
        
        System.out.println("各语言的长度: " + lengths);
        
        // Stream API - 排序
        List<String> sorted = languages.stream()
            .sorted()
            .collect(Collectors.toList());
        
        System.out.println("按字母排序: " + sorted);
        
        // Stream API - 自定义排序
        List<String> sortedByLength = languages.stream()
            .sorted(Comparator.comparing(String::length))
            .collect(Collectors.toList());
        
        System.out.println("按长度排序: " + sortedByLength);
        
        // Stream API - 统计
        long count = languages.stream()
            .filter(lang -> lang.startsWith("J"))
            .count();
        
        System.out.println("以J开头的语言数量: " + count);
        
        // forEach方法
        System.out.println("\n使用forEach方法:");
        languages.forEach(lang -> System.out.print(lang + " "));
        System.out.println();
        
        // 方法引用
        System.out.println("\n使用方法引用:");
        languages.forEach(System.out::println);
        
        // Map的新方法
        Map<String, Integer> yearMap = new HashMap<>();
        yearMap.put("Java", 1995);
        yearMap.put("Python", 1991);
        
        // computeIfAbsent
        yearMap.computeIfAbsent("Ruby", k -> 1995);
        yearMap.computeIfAbsent("Java", k -> 2000); // 已存在，不会计算
        
        // computeIfPresent
        yearMap.computeIfPresent("Python", (k, v) -> v - 2);
        
        // getOrDefault
        int cYear = yearMap.getOrDefault("C", 1972);
        
        System.out.println("\nMap操作后的结果: " + yearMap);
        System.out.println("C的发布年份（默认值）: " + cYear);
        
        // removeIf
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        numbers.removeIf(n -> n % 2 == 0); // 移除所有偶数
        
        System.out.println("\n移除偶数后: " + numbers);
        
        // Optional
        Optional<String> optional = Optional.ofNullable(getLanguage());
        System.out.println("\nOptional示例:");
        optional.ifPresent(lang -> System.out.println("语言: " + lang));
        String result = optional.orElse("Unknown");
        System.out.println("结果: " + result);
    }
    
    /**
     * 可能返回null的方法，用于演示Optional
     */
    private static String getLanguage() {
        // 模拟可能返回null的情况
        return Math.random() > 0.5 ? "Java" : null;
    }
} 